package business.server;

import demo.storage.LogEntry;

import java.io.Serializable;
import java.util.Map;

/**
 * 状态机接口
 * 
 * <p>状态机是Raft算法与业务逻辑的桥梁，负责执行已提交的日志条目。
 * 在实际业务中，状态机可以是：</p>
 * <ul>
 *   <li><b>KV存储</b>：实现分布式键值数据库</li>
 *   <li><b>配置中心</b>：管理应用配置信息</li>
 *   <li><b>任务调度</b>：分布式任务调度系统</li>
 *   <li><b>消息队列</b>：实现可靠的消息传递</li>
 * </ul>
 * 
 * <p><b>核心原则：</b></p>
 * <ul>
 *   <li>确定性：相同的命令序列产生相同的结果</li>
 *   <li>幂等性：重复执行相同命令不会产生副作用</li>
 *   <li>原子性：每个命令的执行要么完全成功，要么完全失败</li>
 * </ul>
 * 
 * @author Raft Implementation Team
 * @version 1.0
 * @since 1.0
 */
public interface StateMachine {
    
    /**
     * 应用日志条目到状态机
     * 
     * <p>此方法会按照日志索引的顺序被调用，确保所有节点的状态机状态一致。</p>
     * 
     * @param entry 要应用的日志条目
     * @return 应用结果，可以返回给客户端
     * @throws StateMachineException 如果应用过程中发生错误
     */
    Object apply(LogEntry entry) throws StateMachineException;
    
    /**
     * 创建快照
     * 
     * <p>当日志变得太大时，可以创建状态机快照来压缩存储空间。
     * 快照包含了到某个日志索引为止的所有状态。</p>
     * 
     * @param lastIncludedIndex 快照包含的最后一个日志索引
     * @param lastIncludedTerm 快照包含的最后一个日志条目的任期
     * @return 快照数据
     */
    Snapshot createSnapshot(int lastIncludedIndex, int lastIncludedTerm);
    
    /**
     * 从快照恢复状态机
     * 
     * <p>节点启动时或者接收到Leader的快照时调用此方法。</p>
     * 
     * @param snapshot 要恢复的快照
     */
    void restoreFromSnapshot(Snapshot snapshot);
    
    /**
     * 获取当前状态机的状态信息
     * 
     * @return 状态信息，用于监控和调试
     */
    Map<String, Object> getState();
    
    /**
     * 检查命令是否有效
     * 
     * <p>在应用命令之前进行验证，可以提前发现无效命令。</p>
     * 
     * @param command 要验证的命令
     * @return 如果命令有效返回true，否则返回false
     */
    boolean isValidCommand(String command);
    
    /**
     * 获取当前已应用的最后一个日志索引
     * 
     * @return 最后应用的日志索引
     */
    int getLastAppliedIndex();
    
    /**
     * 状态机异常
     */
    class StateMachineException extends Exception {
        public StateMachineException(String message) {
            super(message);
        }
        
        public StateMachineException(String message, Throwable cause) {
            super(message, cause);
        }
    }
    
    /**
     * 快照数据
     */
    interface Snapshot extends Serializable {
        /**
         * @return 快照包含的最后一个日志索引
         */
        int getLastIncludedIndex();
        
        /**
         * @return 快照包含的最后一个日志条目的任期
         */
        int getLastIncludedTerm();
        
        /**
         * @return 快照的原始数据
         */
        byte[] getData();
        
        /**
         * @return 快照的校验和，用于验证数据完整性
         */
        String getChecksum();
        
        /**
         * @return 快照创建时间
         */
        long getTimestamp();
    }
} 